package com.kamistoat.meimeistore.order.listener;

import com.kamistoat.common.To.RabbitMQTo.SecKillOrderTo;
import com.kamistoat.common.runTimeFunc.RunTimeLog;
import com.kamistoat.meimeistore.order.To.OrderCreateTo;
import com.kamistoat.meimeistore.order.service.OrderService;
import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;

@Service
public class SecKillOrderListener {
    @Autowired
    OrderService orderService;

    /**
     * 最初的秒杀订单逻辑。只做简单演示
     * @param message
     * @param secKillOrderTo
     * @param channel
     */
    @RabbitListener(queues = "order.seckill.order.queue")
    public void secKillOrderListener(Message message, SecKillOrderTo secKillOrderTo, Channel channel) {
        RunTimeLog.printRunTimeLog("监听到秒杀订单==>" + secKillOrderTo.getOrderSn());
        // 向RabbitMQ手动进行ack
        long deliveryTag = message.getMessageProperties().getDeliveryTag();
        try {
            // 直接将秒杀订单操作也放在try中，防止出现异常
            orderService.secKillOrder(secKillOrderTo);
            // 假如关单服务异常，或者手动ack时异常，都会进入catch
            // 注意第二个参数 false 不是传递false回调，是是否将之前的消息一并ack
            channel.basicAck(deliveryTag, false);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 改进后的秒杀实现。和原有的订单逻辑对接。
     * 当秒杀成功创建订单(未支付状态)，订单被发送到该队列中。该队列将未支付订单入库.
     * @param message
     * @param orderCreateTo
     * @param channel
     */
    @RabbitListener(queues = "order.seckill.new.order.queue")
    public void secKillNewOrderListener(Message message, OrderCreateTo orderCreateTo, Channel channel) {
        RunTimeLog.printRunTimeLog("监听到新创建的未支付秒杀订单:" + orderCreateTo.getOrderEntity().getOrderSn());
        // 向RabbitMQ手动进行ack
        long deliveryTag = message.getMessageProperties().getDeliveryTag();
        try {
            // 将未支付状态的秒杀订单保存入库
            orderService.saveSeckillNewOrder(orderCreateTo);
            // 假如服务异常，或者手动ack时异常，都会进入catch
            // 注意第二个参数 false 不是传递false回调，是是否将之前的消息一并ack
            channel.basicAck(deliveryTag, false);
        } catch (IOException e) {
            RunTimeLog.printRunTimeLog("保存未支付订单出现异常:" + orderCreateTo.getOrderEntity().getOrderSn());
            e.printStackTrace();
        }
    }
}
